package com.azt.front.utils;

import com.azt.api.pojo.Company;
import com.azt.api.pojo.PinganAccount;
import com.azt.api.pojo.PinganAmountIn;
import com.azt.api.pojo.PinganAmountOut;
import com.azt.api.service.*;
import com.azt.exception.BaseException;
import com.azt.provider.utils.BankInterface;
import com.azt.provider.utils.SpringApplicationContextHolder;
import com.azt.utils.BeanUtils;
import com.azt.utils.DESUtils;
import com.azt.utils.MyStringUtils;
import com.xiaoleilu.hutool.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.HashMap;

public class PAMessageHandler extends Thread {
	public static final String RSP_SUCC_CODE = "000000";// 默认交易成功应答码
	private static final String RSP_SUCC_MSG = "交易成功";// 默认交易 成功应答描述
	private static final String CODE_UNDEFINED = "ERR935";// 交易码不存在
	private static final String NO_RECORD = "ERR020";// 记录不存在
	private static final String ERROR_FUNCTION = "ERR021";// 错误的功能码
	private static final String ERROR_COMPANY = "ERR093";// 交易网会员代码输入错误
	private static final String AZT_ERROR = "ERR091";// 交易网返回失败描述

	PAMessageListener mParent = null;

	private PinganAccountService pinganAccountService = (PinganAccountService) SpringApplicationContextHolder
			.getSpringBean("pinganAccountServiceImpl");

	private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

	public static Logger logger = LoggerFactory.getLogger("paInfo");
	public static Logger loggerError = LoggerFactory.getLogger("paError");

	Socket mSocket = null;
	boolean mStopped = false;
	BufferedWriter mWriter = null;
	BufferedReader mReader = null;

	private BankInterface msg = new BankInterface();

	public PAMessageHandler() {
	}

	/**
	 * 创建新的消息处理器
	 * 
	 * @param pSocket
	 */
	public PAMessageHandler(PAMessageListener pParent, Socket pSocket) {
		logger.info("创建新的消息处理器");
		mParent = pParent;
		mSocket = pSocket;
	}

	// 打开并监听socket
	public void run() {
		char tagChar[];
		tagChar = new char[1024];
		int len;
		String temp;
		String rev = "";
		/*	try {
			while (!mStopped && !mSocket.isClosed()) {
				logger.info("处理消息...");
				mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "gbk"));
				mWriter = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "gbk"));

				if ((len = mReader.read(tagChar)) != -1) {
					temp = new String(tagChar, 0, len);
					rev += temp;
					temp = null;
				}
				handleMessage(rev, mWriter);
				closeSocket();
			}
		} catch (Exception e) {
			loggerError.error("error in MessageHandler -- closing down.错误：", e);
			e.printStackTrace();
		}*/
		try {
//		 while (! mStopped && ! mSocket.isClosed()) {
			      logger.info("handling messages.");
			      mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream() , "gbk"));
                  mWriter = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream() , "gbk"));
//                 if ((len = mReader.read(tagChar)) != -1) {
//                     temp = new String(tagChar, 0, len);
//                     rev += temp;
//                     temp = null;
//                 }
			      handleMessage(mReader.readLine() , mWriter);
//			        }
			      } catch (Exception e) {
			        System.out.println("error in MessageHandler -- closing down.");
			       e.printStackTrace();
        }
			      
			     cleanup();

	}
	void handleMessage(String pMessage , BufferedWriter bwriter) throws IOException
	{
        if (pMessage != null) {
//            logger.info( "handling message: '" + pMessage + "'.");
            logger.info("进入消息处理方法...");
            logger.info("报文：" + pMessage);

            HashMap retKeyDict = msg.parsingTranMessageString(pMessage);// 存放解析出来的请求报文的参数

            // logger.info("银行发送报文解析后：" + retKeyDict.toString());

            // 读取交易码
            Integer TranFunc = Integer.parseInt(retKeyDict.get("TranFunc").toString());

            String back = "";

            switch (TranFunc) {
                case 1303:
                    back = getBackMessage_1303(retKeyDict);
                    break;// 签约解约
                case 1310:
                    back = getBackMessage_1310(retKeyDict);
                    break;// 银行发起入金
                case 1312:
                    back = getBackMessage_1312(retKeyDict);
                    break;// 银行发起出金
                case 1019:
                    back = getBackMessage_1019(retKeyDict);
                    break;// 银行查交易网会员余额
                case 1326:
                    back = getBackMessage_1326(retKeyDict);
                    break;// 复核支付银行通知回调
            }

            bwriter.write(back + "\r\n");
            bwriter.flush();
            bwriter.close();
        }
        else
        {
            closeSocket();
        }
	}
	void cleanup() {
		mParent.removeHandler(this);
	}

	/**
	 * 处理接收到的消息
	 * 
	 * @param pMessage
	 * @throws IOException
	 */
	public void handleMessage2(String pMessage, BufferedWriter bwriter) throws IOException {
		logger.info("进入消息处理方法...");
		logger.info("报文：" + pMessage);

		HashMap retKeyDict = msg.parsingTranMessageString(pMessage);// 存放解析出来的请求报文的参数

		// logger.info("银行发送报文解析后：" + retKeyDict.toString());

		// 读取交易码
		Integer TranFunc = Integer.parseInt(retKeyDict.get("TranFunc").toString());

		String back = "";

		switch (TranFunc) {
		case 1303:
			back = getBackMessage_1303(retKeyDict);
			break;// 签约解约
		case 1310:
			back = getBackMessage_1310(retKeyDict);
			break;// 银行发起入金
		case 1312:
			back = getBackMessage_1312(retKeyDict);
			break;// 银行发起出金
		case 1019:
			back = getBackMessage_1019(retKeyDict);
			break;// 银行查交易网会员余额
		case 1326:
			back = getBackMessage_1326(retKeyDict);
			break;// 复核支付银行通知回调
		}

		bwriter.write(back + "\r\n");
		bwriter.flush();
		bwriter.close();
	}

	public static void main(String[] args) {
		// MessageHandler mh = new MessageHandler();
		// try {
		// mh.handleMessage("A0010301018981
		// 0000000283000000EB001012017022019304217022058457746 999999
		// 00000000000000000000000000000130301 20170220193042999999
		// 000000161EB00117022058457746
		// 89811&11005109404201&888800117391921&平安测试六零零零六四四四六五九九&1483D06986093541&52&12342195-X&11014847233002&3&1&平安测试六零零零六四四四六五九九&&平安银行&&&"
		// , null);
		// } catch (IOException e) {
		// e.printStackTrace();
		// }
		// try {
		// String bw=" 20170217102427ERR091绛捐妭绾﹀け璐ワ細";
		// byte[] a = bw.getBytes("GBK");
		// String sss=new String(a,"UTF-8");
		// System.out.println( sss );
		// } catch (UnsupportedEncodingException e) {
		// e.printStackTrace();
		// }
	}

	/**
	 * 银行端签解约
	 * 
	 * @param retKeyDict
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBackMessage_1303(HashMap retKeyDict) throws UnsupportedEncodingException {

		logger.info("进入签解约方法...");
		CompanyService companyService = (CompanyService) SpringApplicationContextHolder
				.getSpringBean("companyServiceImpl");

		HashMap parmaKeyDict = new HashMap();// 存放准备返回的报文参数

		// 读取报文体内容
		String TranFunc = retKeyDict.get("TranFunc").toString();// 交易码
		String FuncFlag = (String) retKeyDict.get("FuncFlag");// 功能标志
		String ThirdCustId = (String) retKeyDict.get("ThirdCustId");// 会员代码

		logger.info("签解约！ThirdCustId:" + ThirdCustId);

		String rspCode = RSP_SUCC_CODE;// 应答码
		String repMsg = RSP_SUCC_MSG;// 应答码描述
		String thirdLogNo = MyStringUtils.getSerialNum();// 流水号

		try {
			if (StrUtil.isNotBlank(FuncFlag)) {
				String cid = DESUtils.decryptToCompanyId(ThirdCustId);
				logger.info("签解约企业id:" + cid);
				Company company = companyService.getCompanyById(Integer.parseInt(cid));// 签约企业
				if (company != null) {
					PinganAccount account = pinganAccountService.getValidAccountByCompanyId(company.getId());
					if ("1".equals(FuncFlag)) {// 功能是指定时
						if (company.getSignPingan().compareTo(1) == 0 || account != null) {
							rspCode = ERROR_COMPANY;// 已经签约了
							repMsg = "交易网会员已经签约";
						} else {// 正式开始签约
							try {
								repMsg = "签约成功";
								PinganAccount pa = new PinganAccount(retKeyDict);
								pa.setCompanyId(company.getId());
								pa.setThirdLogNo(thirdLogNo);
								pa.setRspCode(rspCode);
								pa.setRspMsg(repMsg);
								pinganAccountService.insertAccount(pa);// 绑定签约
							} catch (Exception e) {
								// e.printStackTrace();
								loggerError.error("签约失败", e);
								rspCode = AZT_ERROR;// 签约绑定失败
								repMsg = "签约绑定失败！";
							}
						}
					}
					if ("2".equals(FuncFlag)) {// 功能是修改时
						if (account != null) {
							try {
								PinganAccount pa = new PinganAccount(retKeyDict);
								pa.setThirdLogNo(thirdLogNo);
								BeanUtils.copyBeanNotNull2Bean(pa, account, "createtime");
								account.setRspCode(rspCode);
								account.setRspMsg(repMsg);
								pinganAccountService.updateAccount(account);// 更新平安账户信息
								repMsg = "签约修改成功";
							} catch (Exception e) {
								// e.printStackTrace();
								loggerError.error("修改签约失败", e);
								rspCode = AZT_ERROR;// 签约绑定失败
								repMsg = "修改签约绑定失败！";
							}
						} else {
							rspCode = AZT_ERROR;// 签约绑定失败
							repMsg = "修改失败，交易网未签约绑定";
						}
					}
					if ("3".equals(FuncFlag)) {// 功能是删除时
						if (account != null) {
							pinganAccountService.deleteAccount(account);
							repMsg = "解除签约成功";
						} else {
							rspCode = AZT_ERROR;// 签约绑定失败
							repMsg = "销户失败，交易网未签约绑定";
						}
					}
				} else {
					rspCode = ERROR_COMPANY;// 企业记录不存在
					repMsg = "交易网会员记录不存在";
				}
			} else {
				rspCode = ERROR_FUNCTION;// 功能标志错误
				repMsg = "功能标志不存在";
			}
		} catch (IllegalArgumentException ie) {
			loggerError.error("签约失败，交易网会员代码有误", ie);
			rspCode = AZT_ERROR;// 功能标志错误
			repMsg = "签约失败，交易网会员代码有误";
		} catch (Exception e) {
			// e.printStackTrace();
			loggerError.error("签解约失败", e);
			rspCode = AZT_ERROR;// 功能标志错误
			repMsg = "签解约失败：" + e.getMessage();
		}

		logger.info(repMsg);

		// 组返回报文
		/* 报文参数赋值 */
		parmaKeyDict.put("RspCode", rspCode);// 应答码
		parmaKeyDict.put("RspMsg", repMsg);// 应答描述
		parmaKeyDict.put("TranFunc", TranFunc);// 交易码
		parmaKeyDict.put("ThirdLogNo", thirdLogNo); // 返回流水号
		parmaKeyDict.put("Reserve", "");

		String back = msg.getReturnTranMessage(parmaKeyDict);
		logger.info("back:" + back);

		return back;
	}

	/**
	 * 银行端入金回调
	 * 
	 * @param retKeyDict
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBackMessage_1310(HashMap retKeyDict) throws UnsupportedEncodingException {

		logger.info("进入银行入金回调方法...");
		PinganAmountInService pinganAmountInService = (PinganAmountInService) SpringApplicationContextHolder
				.getSpringBean("pinganAmountInServiceImpl");

		HashMap parmaKeyDict = new HashMap();// 存放准备返回的报文参数

		// 读取报文体内容
		String TranFunc = retKeyDict.get("TranFunc").toString();// 交易码
		String CustAcctId = (String) retKeyDict.get("CustAcctId");// 子账户id
		String CcyCode = (String) retKeyDict.get("CcyCode");// 币种

		logger.info("入金子账户ID：CustAcctId:" + CustAcctId);

		String rspCode = RSP_SUCC_CODE;// 应答码
		String repMsg = RSP_SUCC_MSG;// 应答码描述
		String thirdLogNo = MyStringUtils.getSerialNum();// 流水号

		try {
			if (StrUtil.isNotBlank(CustAcctId)) {
				PinganAccount account = pinganAccountService.getAccountByCustAcctId(CustAcctId);
				if (account != null) {
					try {
						if (BankInterface.DEFAULT_CCY_CODE.equals(CcyCode)) {
							PinganAmountIn pai = new PinganAmountIn(retKeyDict);
							pai.setRspCode(rspCode);
							pai.setRspMsg(repMsg);
							pai.setThirdLogNo(thirdLogNo);
							pai.setAccountId(account.getId());
							pinganAmountInService.insertAmountIn(pai);
						}
					} catch (Exception e) {
						// e.printStackTrace();
						loggerError.error("银行端入金失败", e);
						rspCode = AZT_ERROR;// 入金保存失败
						repMsg = "入金失败";
					}

				} else {
					rspCode = AZT_ERROR;// 交易网绑定记录不存在
					repMsg = "交易网绑定记录不存在";
				}
			} else {
				rspCode = AZT_ERROR;// 入金子账户ID未接收到
				repMsg = "入金子账户ID未接收到";
			}
		} catch (Exception e) {
			// e.printStackTrace();
			loggerError.error("银行端入金失败", e);
			rspCode = AZT_ERROR;// 功能标志错误
			repMsg = "入金失败";
		}

		logger.info(repMsg);

		// 组返回报文
		/* 报文参数赋值 */
		parmaKeyDict.put("RspCode", rspCode);// 应答码
		parmaKeyDict.put("RspMsg", repMsg);// 应答描述
		parmaKeyDict.put("TranFunc", TranFunc);// 交易码
		parmaKeyDict.put("ThirdLogNo", thirdLogNo); // 返回流水号
		parmaKeyDict.put("Reserve", "");

		String back = msg.getReturnTranMessage(parmaKeyDict);
		logger.info("back:" + back);

		return back;
	}

	/**
	 * 银行端发起出金
	 * 
	 * @param retKeyDict
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBackMessage_1312(HashMap retKeyDict) throws UnsupportedEncodingException {

		logger.info("进入银行出金回调方法...");

		PinganAmountOutService pinganAmountOutService = (PinganAmountOutService) SpringApplicationContextHolder
				.getSpringBean("pinganAmountOutServiceImpl");

		HashMap parmaKeyDict = new HashMap();// 存放准备返回的报文参数

		// 读取报文体内容
		String TranFunc = retKeyDict.get("TranFunc").toString();// 交易码
		String CustAcctId = (String) retKeyDict.get("CustAcctId");// 子账户id
		String CcyCode = (String) retKeyDict.get("CcyCode");// 币种

		logger.info("出金子账户ID：CustAcctId:" + CustAcctId);

		String rspCode = RSP_SUCC_CODE;// 应答码
		String repMsg = RSP_SUCC_MSG;// 应答码描述
		String thirdLogNo = MyStringUtils.getSerialNum();// 流水号

		try {
			if (StrUtil.isNotBlank(CustAcctId)) {
				PinganAccount account = pinganAccountService.getAccountByCustAcctId(CustAcctId);
				if (account != null) {
					try {
						if (BankInterface.DEFAULT_CCY_CODE.equals(CcyCode)) {
							PinganAmountOut pao = new PinganAmountOut(retKeyDict);
							pao.setRspCode(rspCode);
							pao.setRspMsg(repMsg);
							pao.setThirdLogNo(thirdLogNo);
							pao.setAccountId(account.getId());
							pinganAmountOutService.insertAmountOut(pao);
						}
					} catch (Exception e) {
						// e.printStackTrace();
						loggerError.error("银行端出金失败", e);
						rspCode = AZT_ERROR;// 入金保存失败
						repMsg = "出金失败";
					}

				} else {
					rspCode = AZT_ERROR;// 交易网绑定记录不存在
					repMsg = "交易网绑定记录不存在";
				}
			} else {
				rspCode = AZT_ERROR;// 入金子账户ID未接收到
				repMsg = "出金子账户ID未接收到";
			}
		} catch (Exception e) {
			loggerError.error("银行端出金失败", e);
			rspCode = AZT_ERROR;// 功能标志错误
			repMsg = "出金失败";
		}

		logger.info(repMsg);

		// 组返回报文
		/* 报文参数赋值 */
		parmaKeyDict.put("RspCode", rspCode);// 应答码
		parmaKeyDict.put("RspMsg", repMsg);// 应答描述
		parmaKeyDict.put("TranFunc", TranFunc);// 交易码
		parmaKeyDict.put("ThirdLogNo", thirdLogNo); // 返回流水号
		parmaKeyDict.put("Reserve", "");

		String back = msg.getReturnTranMessage(parmaKeyDict);
		logger.info("back:" + back);

		return back;
	}

	/**
	 * 银行查交易网会员余额
	 * 
	 * @param retKeyDict
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBackMessage_1019(HashMap retKeyDict) throws UnsupportedEncodingException {

		logger.info("进入查询交易网会员余额方法...");

		HashMap parmaKeyDict = new HashMap();// 存放准备返回的报文参数

		// 读取报文体内容
		String TranFunc = retKeyDict.get("TranFunc").toString();// 交易码
		String CustAcctId = (String) retKeyDict.get("CustAcctId");// 子账户id

		logger.info("被查询子账户ID：CustAcctId:" + CustAcctId);

		String rspCode = RSP_SUCC_CODE;// 应答码
		String repMsg = RSP_SUCC_MSG;// 应答码描述
		String thirdLogNo = MyStringUtils.getSerialNum();// 流水号
		String ThirdCustId = "";
		String CustName = "";
		String TotalAmount = "";
		String TotalBalance = "";
		String TotalFreezeAmount = "";
		String TranDate = "";

		if (StrUtil.isNotBlank(CustAcctId)) {
			PinganAccount account = pinganAccountService.getAccountByCustAcctId(CustAcctId);
			if (account != null) {
				ThirdCustId = account.getThirdCustId();
				CustName = account.getCustName();
				TotalAmount = String.valueOf(account.getTranAmount() + account.getFrozenAmount());
				TotalBalance = String.valueOf(account.getTranAmount());
				TotalFreezeAmount = String.valueOf(account.getFrozenAmount());
				TranDate = sdf.format(account.getUpdatetime());
			} else {
				rspCode = AZT_ERROR;// 交易网绑定记录不存在
				repMsg = "交易网绑定记录不存在";
			}
		} else {
			rspCode = AZT_ERROR;// 入金子账户ID未接收到
			repMsg = "出金子账户ID未接收到";
		}

		logger.info(repMsg);

		// 组返回报文
		/* 报文参数赋值 */
		parmaKeyDict.put("RspCode", rspCode);// 应答码
		parmaKeyDict.put("RspMsg", repMsg);// 应答描述
		parmaKeyDict.put("TranFunc", TranFunc);// 交易码
		parmaKeyDict.put("ThirdLogNo", thirdLogNo); // 返回流水号
		parmaKeyDict.put("CustAcctId", CustAcctId); // 子账户
		parmaKeyDict.put("ThirdCustId", ThirdCustId); // 交易网会员代码
		parmaKeyDict.put("CustName", CustName); // 会员名称
		parmaKeyDict.put("TotalAmount", TotalAmount); // 账户总余额
		parmaKeyDict.put("TotalBalance", TotalBalance); // 账户可用余额
		parmaKeyDict.put("TotalFreezeAmount", TotalFreezeAmount); // 账户总冻结金额
		parmaKeyDict.put("TranDate", TranDate); // 维护日期
		parmaKeyDict.put("Reserve", "");

		String back = msg.getReturnTranMessage(parmaKeyDict);
		logger.info("back:" + back);

		return back;
	}

	/**
	 * 复核支付银行通知回调
	 * 
	 * @param retKeyDict
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBackMessage_1326(HashMap retKeyDict) throws UnsupportedEncodingException {

		logger.info("进入复核支付银行通知回调方法...");
		OrderService orderService = (OrderService) SpringApplicationContextHolder.getSpringBean("orderServiceImpl");

		HashMap parmaKeyDict = new HashMap();// 存放准备返回的报文参数

		// 读取报文体内容
		String TranFunc = retKeyDict.get("TranFunc").toString();// 交易码
		String FuncFlag = (String) retKeyDict.get("FuncFlag");// 功能标志 1：支付复核
		String CheckResult = (String) retKeyDict.get("CheckResult");// 复核结果
																	// Y：复核通过
																	// N：复核拒绝
		String CcyCode = (String) retKeyDict.get("CcyCode");// 币种
		String ThirdHtId = (String) retKeyDict.get("ThirdHtId");// 订单号
		String PaySerialNo = (String) retKeyDict.get("PaySerialNo");// 原支付指令号

		logger.info("复核通知，订单号:" + ThirdHtId + "，指令号：" + PaySerialNo + "，通知结果：" + CheckResult);

		String rspCode = RSP_SUCC_CODE;// 应答码
		String repMsg = RSP_SUCC_MSG;// 应答码描述
		String thirdLogNo = MyStringUtils.getSerialNum();// 流水号
		retKeyDict.put("ThirdLogNo", thirdLogNo);

		if ("1".equals(FuncFlag) && BankInterface.DEFAULT_CCY_CODE.equals(CcyCode)) {
			try {
				orderService.auditOrderForPingan(retKeyDict);
				repMsg = "复核成功";
			} catch (BaseException e) {
				loggerError.error("交易网复核失败", e);
				rspCode = AZT_ERROR;
				repMsg = e.getErrorCode();
			}
		} else {
			rspCode = AZT_ERROR;
			repMsg = "复核通知功能标志有误或币种非RMB";
		}

		logger.info(repMsg);

		// 组返回报文
		/* 报文参数赋值 */
		parmaKeyDict.put("RspCode", rspCode);// 应答码
		parmaKeyDict.put("RspMsg", repMsg);// 应答描述
		parmaKeyDict.put("TranFunc", TranFunc);// 交易码
		parmaKeyDict.put("ThirdLogNo", thirdLogNo); // 返回流水号
		parmaKeyDict.put("Reserve", "");

		String back = msg.getReturnTranMessage(parmaKeyDict);
		logger.info("back:" + back);

		return back;
	}

	/**
	 * 关闭socket.
	 */
	public void closeSocket() throws IOException {
		mSocket.close();
	}

	/**
	 * 停止处理器.
	 */
	void stopHandler() {
		mStopped = true;

		try {
			closeSocket();
		} catch (Exception e) {
			// ignore--we're stopping.
		}
	}
}
